<?php

namespace Viettrans\FrontBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\FormError;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

use Viettrans\FrontBundle\Entity\User;
use Viettrans\FrontBundle\Form\UserType;
use Viettrans\FrontBundle\Form\NoPersist\LoginUser;

/**
 * User controller.
 *
 * @Route("/user")
 */
class UserController extends Controller
{
    /**
     * Lists all User entities.
     *
     * @Route("/", name="user")
     * @Template()
     */
    public function indexAction()
    {
        $em = $this->getDoctrine()->getEntityManager();

        $entities = $em->getRepository('ViettransFrontBundle:User')->findAll();

        return array('entities' => $entities);
    }
	
	/**
	 * Show form login action
	 * @Route("/login", name="user_login")
	 * @Template()
	 */
	public function loginAction() {
		# Create the form and assign (bind) the form to user object
		$form  = $this->createForm(new LoginUser());
		
        # Get request object
        $request = $this->getRequest();

        # Check if the form is submited
        if ('POST' === $request->getMethod()) {
            # Bind the request to the form
            # !!! Important:
            # All the form fields will be filled with the values in request object
            # Since the form is binded to user object, the corresponding properties of user object will be assigned here
			$form->bindRequest($request);
			
			$formData = $request->get('form_user_login');
			
			$em = $this->getDoctrine()->getEntityManager();
			
			$user = $em->getRepository('ViettransFrontBundle:User')->findOneByEmail($formData['email']);
			
			# Email does not exist
			if (!$user) $form->addError(new FormError('Email không tồn tại.'));
			
			# Password does not match
			else if ($user->getPassword() != $formData['password']) $form->addError(new FormError('Mật khẩu không đúng.'));
			
			# Login OK !
			else {
				$userId = $user->getId();
			
				$session = $this->get('session');
				
				$session->set('token', $this->generateToken($userId));
				$session->set('userId', $userId);
				
				# Redirect to the offer page
				return $this->redirect($this->generateUrl('announcement_offer'));
			}
		}
		
        return array (
            'form' => $form->createView()
        );
	}
	
	/**
	 * Show form login action
	 * @Route("/logout", name="user_logout")
	 */
	public function logoutAction() {
		$session = $this->get('session');
		$session->remove('userId');
		$session->remove('token');
		
		return $this->redirect($this->generateUrl('announcement_offer'));
	}
	
	/**
	 * Show form forgot password
	 * @Route("/forgot_password", name="user_forgot_password")
	 * @Template()
	 */
	public function forgotPasswordAction() {
		$request = $this->getRequest();

		$form = $this->createFormBuilder('',array('csrf_protection' => false))
					 ->add('email', 'email', array('label' => 'Email', 'trim' => true))
					 ->getForm();
		
		if($request->getMethod() === 'POST') {
			$form->bindRequest($request);
		
			$formData = $request->get('form');
			$email = $formData['email'];
			
			$emailPattern = "/^[-a-z0-9!#$%&'*+\/=?^_`{|}~]+(\.[-a-z0-9!#$%&'*+\/=?^_`{|}~]+)*@(([a-z0-9]([-a-z0-9]*[a-z0-9]+)?){1,63}\.)+([a-z0-9]([-a-z0-9]*[a-z0-9]+)?){2,63}$/i";
			
			$isEverythingOk = true;
			
			if (trim($email) == '' || !preg_match($emailPattern, $email)) {
				$isEverythingOk = false;
				$form->addError(new FormError('Email không hợp lệ.'));
			}
			
			$user = $this->getDoctrine()->getEntityManager()->getRepository('ViettransFrontBundle:User')->findOneByEmail($email);

			if (!$user) {
				$isEverythingOk = false;
				$form->addError(new FormError('Email không tồn tại trong hệ thống.'));
			}
			
			if ($isEverythingOk) {
				# Send email
				$message = \Swift_Message::newInstance()
					->setSubject('Viettrans - Email quên mật khẩu từ Viettrans.net')
					->setFrom(array(
						'no-reply@viettrans.net' => 'Viettrans'
					))
					->setReplyTo('no-reply@viettrans.net')
					->setTo(array(
						$email => $user->getName()
					))
					->setBody($this->renderView('ViettransFrontBundle:Email:userForgotPassword.html.twig', array(
						'user' => $user
					)), 'text/html', 'utf-8');
				
				# If unable to send email
				if (!$this->get('mailer')->send($message)) {
					$form->addError(new FormError('Có lỗi khi gửi email quên mật khẩu.'));
				
				# If send email successfully then redirect to success page
				} else {
					# Set flash message
					$this->get('session')->setFlash('message', 'Mật khẩu đã được gửi tới email của bạn.');
					
					return $this->redirect($this->generateUrl('default_success'));
				}
			}
		}
		
		return array(
			'form' => $form->createView()
		);
	}
	
    /**
     * Finds and displays a User entity.
     *
     * @Route("/{id}/show", name="user_show")
     * @Template()
     */
    public function showAction($id) {
        $em = $this->getDoctrine()->getEntityManager();

        $entity = $em->getRepository('ViettransFrontBundle:User')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find User entity.');
        }

        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'delete_form' => $deleteForm->createView(),        );
    }

    /**
     * Displays a form to create a new User entity.
     *
     * @Route("/new", name="user_new")
     * @Template()
     */
    public function newAction() {
		# Create new instance of class User, it's just an empty object
        $user = new User();
		
		# Create the form and assign (bind) the form to user object
        $form  = $this->createForm(new UserType($this->container), $user);

        # Get request object
        $request = $this->getRequest();
		
        # Check if the form is submited
        if ('POST' === $request->getMethod()) {
            # Bind the request to the form
            # !!! Important:
            # All the form fields will be filled with the values in request object
            # Since the form is binded to annoucement object, the corresponding properties of user object will be assigned here
			$form->bindRequest($request);
			
			# Transform email to lower case
			$user->setEmail(strtolower($user->getEmail()));
			
            # Check the form validity
            if ($form->isValid()) {
			    # Get entity manager object
				$em = $this->getDoctrine()->getEntityManager();
				
				# Check form data
				$isEverythingOk = true;
				
				# Check Locality. Format: name (code). Ex: Maison Alfort (94140)
				$locality = $user->getLocality();

				# Check locality
				# Get Repos
				$townRepo = $em->getRepository('ViettransFrontBundle:Town');
				$town = $townRepo->getTownByLocality($locality);
				
				# If the corresponding town does not exist then show the error
				if (!$town) {
					$isEverythingOk = false;
					$form->addError(new FormError('Thành phố không hợp lệ. Bạn phải chọn thành phố trong danh sách gợi ý.'));
				}

				# Check email unique
				# Get Repos
				$userRepo = $em->getRepository('ViettransFrontBundle:User');
				$userByEmail = $userRepo->findOneByEmail($user->getEmail());

				# If the corresponding town does not exist then show the error
				if ($userByEmail) {
					# If user exists and is activated then do not allow to create the new user
					if ($userByEmail->getIsActivated()) {
						$isEverythingOk = false;
						$form->addError(new FormError('Địa chỉ email này đã được đăng kí.'));
					
					# If user exists but not yet activated then replace by the new user
					} else {
						$em->remove($userByEmail);
						$em->flush();
					}
				}
				
                # If everything is ok then create new user
                if ($isEverythingOk) {
					#By default the user is not activated yet
					$user->setIsActivated(false);
					$user->setTownId($town->getId());
					
					return $this->forward('ViettransFrontBundle:User:create', array(
						'user' => $user
					));
				}
			}
		}
		
        return array (
            'form' => $form->createView()
        );
    }

    /**
     * Creates a new User entity.
     *
     * @Route("/create", name="user_create")
     * @Method("post")
     */
    public function createAction($user) {
		# Get entity manager object
		$em = $this->getDoctrine()->getEntityManager();
		
		# Persist user to db
		# Begin transaction
		$em->getConnection()->beginTransaction();
		
		try {
			# Persist data to db
			$em->persist($user);
			$em->flush();
			
			# Send activation email
			$message = \Swift_Message::newInstance()
				->setSubject('Viettrans - Email kích hoạt tài khoản từ Viettrans.net')
				->setFrom('no-reply@viettrans.net')
				->setTo($user->getEmail())
				->setBody($this->renderView('ViettransFrontBundle:Email:activateUser.html.twig', array(
					'name'   => $user->getName(),
					'activationUrl' => $this->generateUrl('user_activate', array(
						'id'    => $user->getId(),
						'token' => $this->generateToken($user->getId()),
					), true),
				)), 'text/html', 'utf-8');
			
			if (!$this->get('mailer')->send($message)) throw new \Exception('Có lỗi khi gửi mail');
			
			# Commit the transaction
			$em->getConnection()->commit();
			
			# Set flash message
			$this->get('session')->setFlash('message', '
				Tài khoản của bạn đã được tạo thành công.<br>
				Để kích hoạt tài khoản, xin vui lòng kiểm tra email trong hòm thư mà bạn đã đăng kí và làm theo hướng dẫn.
			');
			
			return $this->redirect($this->generateUrl('default_success'));
			
		# Catch the errors
		} catch(\Exception $e) {
			# Rollback the transaction
			$em->getConnection()->rollback();
			$em->close();
			
			$errDetail = '';
			if ($this->container->getParameter('kernel.environment') == 'dev') $errDetail = $e->getMessage();
			
			throw new \Exception('Có lỗi khi tạo tài khoản của bạn. Xin vui lòng liên hệ với admin.'.$errDetail);
		}
    }

    /**
     * Activate user
     *
     * @Route("/activate/{id}/{token}", name="user_activate")
     * @Template()
     */
	public function activateAction($id, $token) {
		# Get session object
        $session = $this->get('session');
	
		# Get entity manager object
		$em = $this->getDoctrine()->getEntityManager();
		
		# Token is not valid
		if ($token !== $this->generateToken($id)) {
			$session->setFlash('message', 'Link kích hoạt của bạn không hợp lệ. Xin vui lòng kiểm tra lại thông tin.');
			
			return $this->redirect($this->generateUrl('default_error'));
		
		# Token is valid
		} else {
			# Get announcement object
			$user = $em->getRepository('ViettransFrontBundle:User')->find($id);

			if (!$user) throw new \Exception("User với id $id không tồn tại.");
			
			# If announcement has been already activated
			if ($user->getIsActivated()) {
				$session->setFlash('message', 'Tài khoản của bạn đã được kích hoạt.');

				return $this->redirect($this->generateUrl('default_error'));
			
			# Activate the announcement
			} else {
				try {
					$user->setIsActivated(true);
					$em->persist($user);
					$em->flush();
					
					$session->setFlash('message', 'Tài khoản của bạn đã được kích hoạt thành công.');
					
					return $this->redirect($this->generateUrl('default_success'));
				
				# In case of error
				} catch (Exception $e) {
					$errDetail = '';
					if ($this->container->getParameter('kernel.environment') == 'dev') $errDetail = $e->getMessage();
				
					$session->setFlash('message', 'Có lỗi không xác định khi kích hoạt tài khoản của bạn. Xin vui lòng liên hệ với admin.'.$errDetail);
					
					return $this->redirect($this->generateUrl('default_error'));
				}
			}
		}
	}
		
    /**
     * Displays a form to edit an existing User entity.
     *
     * @Route("/edit", name="user_edit")
     * @Template()
     */
    public function editAction() {
		$em = $this->getDoctrine()->getEntityManager();
        
		$userId = $this->get('session')->get('userId');
		$user = $em->getRepository('ViettransFrontBundle:User')->find($userId);
		
        if (!$user) return $this->redirect($this->generateUrl('user_login'));
	
		$user->setLocality($user->getTownObj()->getName().' ('.$user->getTownObj()->getCode().')');
		$user->setConfirmPassword($user->getPassword());
		
        $form = $this->createFormBuilder($user, array('csrf_protection' => false))
					 ->add('name',               'text',     array('label' => 'Tên liên hệ',           'trim' => true))
					 ->add('locality',           'text',     array('label' => 'Thành phố',             'trim' => true))
					 ->add('telephone',          'text',     array('label' => 'Điện thoại',            'trim' => true, 'required' => false))
					 ->add('currentPassword',    'password', array('label' => 'Mật khẩu hiện tại',     'trim' => true, 'required' => false))
					 ->add('newPassword',        'password', array('label' => 'Mật khẩu mới',          'trim' => true, 'required' => false))
					 ->add('confirmNewPassword', 'password', array('label' => 'Xác nhận mật khẩu mới', 'trim' => true, 'required' => false))
                     ->getForm();
		
		$request = $this->getRequest();
		
        # Check if the form is submited
        if ('POST' === $request->getMethod()) {
            # Bind the request to the form
			$form->bindRequest($request);
			
            # Check the form validity
            if ($form->isValid()) {
				$isEverythingOk = true;
				
				# Check locality
                $town = $em->getRepository('ViettransFrontBundle:Town')->getTownByLocality($user->getLocality());

                # If the corresponding town does not exist then show the error
                if (!$town) {
                    $isEverythingOk = false;
                    $form->addError(new FormError('Thành phố không hợp lệ. Bạn phải chọn thành phố trong danh sách gợi ý.'));
                }
				
				# Check password
				# If the current password field is not empty then check
				if ($user->getCurrentPassword() != '') {
					# If current password does not match
					if ($user->getCurrentPassword() != $user->getPassword()) {
						$isEverythingOk = false;
						$form->addError(new FormError('Mật khẩu hiện tại không đúng.'));
					
					# If current password is matched then check new password
					} else {
						# If the new password is empty the show the error
						if (trim($user->getNewPassword()) == '') {
							$isEverythingOk = false;
							$form->addError(new FormError('Mật khẩu mới không được để trống.'));
						
						} else {
							# If new password is not empty but does not match with confirm new password
							if ($user->getNewPassword() != $user->getConfirmNewPassword()) {
								$isEverythingOk = false;
								$form->addError(new FormError('Mật khẩu xác nhận không đúng.'));
							
							# If every password is ok then set password
							} else {
								$user->setPassword($user->getNewPassword());
							}
						}
					}
				}
				
				# If everything is Ok then forward the request to the update action
				$user->setTownId($town->getId());
				if ($isEverythingOk) return $this->forward('ViettransFrontBundle:User:update', array('user' => $user));
			}
		}
		
        return array(
            'user' => $user,
            'form' => $form->createView(),
        );
    }

    /**
     * Edits an existing User entity.
     *
     * @Route("/update", name="user_update")
     * @Method("post")
     * @Template("ViettransFrontBundle:User:edit.html.twig")
     */
    public function updateAction() {
		$em = $this->getDoctrine()->getEntityManager();

		$user = $this->getRequest()->get('user');
		
        if (!$user) return $this->redirect($this->generateUrl('user_login'));

		$em->persist($user);
		$em->flush();
		
		$this->get('session')->setFlash('message', 'Thông tin tài khoản đã được thay đổi thành công.');
		
        return $this->redirect($this->generateUrl('user_edit'));
    }

    /**
     * Deletes a User entity.
     *
     * @Route("/{id}/delete", name="user_delete")
     * @Method("post")
     */
    public function deleteAction($id)
    {
        $form = $this->createDeleteForm($id);
        $request = $this->getRequest();

        $form->bindRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getEntityManager();
            $entity = $em->getRepository('ViettransFrontBundle:User')->find($id);

            if (!$entity) {
                throw $this->createNotFoundException('Unable to find User entity.');
            }

            $em->remove($entity);
            $em->flush();
        }

        return $this->redirect($this->generateUrl('user'));
    }

    private function createDeleteForm($id)
    {
        return $this->createFormBuilder(array('id' => $id))
            ->add('id', 'hidden')
            ->getForm()
        ;
    }
	
	private function generateToken($id) {
		$secret = $this->container->getParameter('secret');
		
		return md5($id.$secret);
	}
}
